-
Notifications
You must be signed in to change notification settings - Fork 8.2k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Resolver in timeline #69728
Resolver in timeline #69728
Conversation
This comment has been minimized.
This comment has been minimized.
4ab8422
to
902fa3b
Compare
x-pack/plugins/security_solution/public/timelines/components/timeline/body/helpers.ts
Outdated
Show resolved
Hide resolved
x-pack/plugins/security_solution/public/resolver/store/middleware/resolver_tree_fetcher.ts
Outdated
Show resolved
Hide resolved
x-pack/plugins/security_solution/public/resolver/store/data/selectors.ts
Outdated
Show resolved
Hide resolved
x-pack/plugins/security_solution/public/resolver/store/data/selectors.ts
Outdated
Show resolved
Hide resolved
x-pack/plugins/security_solution/public/resolver/store/data/selectors.ts
Outdated
Show resolved
Hide resolved
* you may not use this file except in compliance with the Elastic License. | ||
*/ | ||
|
||
/* eslint-disable no-duplicate-imports */ |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
❔ what's this for
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
editor automatically fixing superfluous eslint rules
const entityIDToFetch = selectors.entityIDToFetch(state); | ||
|
||
if (selectors.shouldAbortRequest(state) && lastRequest) { | ||
lastRequest.abortController.abort(); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
❔ Should check https://devdocs.io/dom/abortsignal/aborted before .abort
?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The signal
only seems to raise an abort
event once regardless of how many times you call abort, so it's probably fine.
var ac = new AbortController();
var signal = ac.signal;
signal.addEventListener('abort', ()=>{ console.log('aborted') });
ac.abort();
ac.abort();//only logs `abort` once
}); | ||
} catch { | ||
api.dispatch({ | ||
type: 'serverFailedToReturnResolverData', |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
❔ This runs when a signal aborts right? Seems like we should have a distinct catch
for AbortError
and an action like appReceivedAbortSignalDuringResolverDataFetch
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
seems like a good idea. i'm going to try that.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Something like:
} catch (error) {
// https://developer.mozilla.org/en-US/docs/Web/API/DOMException#exception-AbortError
if (error instanceof DOMException && error.name === 'AbortError') {
api.dispatch({
type: 'appAbortedResolverDataRequest',
payload: databaseDocumentIDToFetch,
});
} else {
api.dispatch({
type: 'serverFailedToReturnResolverData',
payload: databaseDocumentIDToFetch,
});
}
}
?
c6d911d
to
08bfddb
Compare
b9756e8
to
627d5f8
Compare
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Need to do some cleanup before merging
/** | ||
* Return each node of the tree. | ||
* used to calculate related event stas | ||
* TODO, this is used twice, by two separate things? probably wrong |
This comment was marked as resolved.
This comment was marked as resolved.
Sorry, something went wrong.
This comment was marked as resolved.
This comment was marked as resolved.
Sorry, something went wrong.
/** | ||
* Test the data reducer and selector. | ||
*/ | ||
describe('Resolver Data Middleware', () => { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@bkimmel i moved your tests here
x-pack/plugins/security_solution/public/resolver/store/data/selectors.test.ts
Outdated
Show resolved
Hide resolved
x-pack/plugins/security_solution/public/resolver/store/data/selectors.test.ts
Outdated
Show resolved
Hide resolved
x-pack/plugins/security_solution/public/resolver/store/data/selectors.test.ts
Outdated
Show resolved
Hide resolved
x-pack/plugins/security_solution/public/resolver/view/styles.tsx
Outdated
Show resolved
Hide resolved
@@ -27,7 +28,7 @@ describe('useCamera on an unpainted element', () => { | |||
let simulator: SideEffectSimulator; | |||
|
|||
beforeEach(async () => { | |||
({ store } = storeFactory()); | |||
store = storeFactory(); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
this was returning an object with the store in it.
@@ -29,7 +29,7 @@ export const TimelineBody = styled.div.attrs(({ className = '' }) => ({ | |||
overflow: auto; | |||
scrollbar-width: thin; | |||
flex: 1; | |||
visibility: ${({ visible }) => (visible ? 'visible' : 'hidden')}; | |||
display: ${({ visible }) => (visible ? 'block' : 'none')}; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
If we use 'visibility'
here, it still occupies space. The parent is 'flex' and Resolver is a sibling of this component. We need Resolver to grow. Seems like display: none
did the trick. Anyone know of any reason why this would be bad?
@XavierM seems to know many things
x-pack/plugins/security_solution/server/endpoint/routes/resolver/entity.ts
Show resolved
Hide resolved
* what happens if there are more matches than can be returned from es? | ||
* do we even need more than one match? | ||
*/ | ||
export function handleEntities( |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@jonathan-buttner if ya get a chance, could ya give it a quick look?
e22f482
to
1d88a9e
Compare
Pinging @elastic/endpoint-app-team (Feature:Endpoint) |
@elasticmachine merge upstream |
Pinging @elastic/endpoint-data-visibility-team (Team:Endpoint Data Visibility) |
endgame: { | ||
process_name: '', | ||
event_type_full: 'process_event', | ||
event_subtype_full: 'creation_event', |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Do we also need to mock the new style endpoint events in ecs?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I don't think it should matter here. The code operates on the ResolverEvent interface which supports either old or new events. As long as the methods works correctly on old and new style events, this code should work. We could also test those methods in isolation.
At some point, old events and new ECS events will probably stop being equivalent to each other. At that point we'd probably want a version of mockProcessEvent
that returns the new style as well. At that point, if we wanted to be exhaustive, we could make a version of the mockProcessEvent
that returned new ECS events and then run these tests w/ those objects as well.
Does that all add up?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Since most of these tests are for code paths that occur after we normalize unique_pid/entity_id I don't think it's super important now
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Sounds good, just wanted to double check 👍
beforeEach(() => { | ||
const generator = new EndpointDocGenerator('seed'); | ||
const tree = mockResolverTree({ | ||
events: generator.generateTree({ ancestors: 1, generations: 2, children: 2 }).allEvents, |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@bkimmel don't know if it matters but the generated tree will have parents with up to 2 children (randomly generated). If you always want the nodes to have exactly 2 children you can pass in alwaysGenMaxChildrenPerNode: true
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I think we should do that
@@ -58,3 +89,5 @@ export const dataReducer: Reducer<DataState, ResolverAction> = (state = initialS | |||
return state; | |||
} | |||
}; | |||
|
|||
// TODO, handle abort scenario |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Do we need to handle this scenario in this PR?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
abort is handled. TODO comment should be removed. ty
result = await context.services.http.get(`/api/endpoint/resolver/${entityIDToFetch}`, { | ||
signal: lastRequestAbortController.signal, | ||
query: { | ||
children: 5, |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Hopefully we can bump these number up after I do some performance testing.
bool: { | ||
filter: [ | ||
{ | ||
match: { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I think we can switch this to an IDs search: https://www.elastic.co/guide/en/elasticsearch/reference/current/query-dsl-ids-query.html
@andrew-goldstein the _id
that we're passing should be the unique ES document ID (i.e. _id
field right) right?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I'll give this a shot
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
worked just fine.
}; | ||
} | ||
|
||
const queryResponse: ExpectedQueryResponse = await context.core.elasticsearch.legacy.client.callAsCurrentUser( |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Should we try/catch
around this? If ES fails for some reason maybe the server should log and return a 500?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Let me look into this.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
👍 Sounds good, thanks for looking.
* ResolverTree type is returned by the server. It organizes events into a complex structure. The | ||
* organization of events in the tree is done to associate metadata with the events. The client does not | ||
* use this metadata. Intsead, the client flattens the tree into an array. Therefore we can safely | ||
* make a malformed RelsoverTree for the purposes of the tests, so long as it is flattened in a predicatable way. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
🤷 Resolver spelled wrong in the comment
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Intsead and predicatable too. (i turned on spellcheck lol)
* This prints out all of the properties of the data state. | ||
* This way we can see the overall behavior of the selector easily. | ||
*/ | ||
const viewAsAString = (dataState: DataState) => { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
👌
💚 Build SucceededBuild metrics
History
To update your PR or re-run it, just comment with: |
Display Resolver in Security Solution's Timeline.
Display Resolver in Security Solution's Timeline.
Summary
based on #70111
This displays resolver in the security solution timeline.
Screenshots
Panning between nodes using the panel, in the timeline
Browsing resolver's via event panel
Loading resolver w/ artificially added latency (to show the loading dialog)
Artificially causing the request for entity_id to fail (the request made with _id)
Artificially causing the main request for resolver data to fail (the request made w/ entity_id)
Some data from the generator, in the timeline (not animated)
To fix before merge
Follow up work
useStateSyncingActions
to model query string.API integration test plan
Checklist
For maintainers